/**
 * 广寒宫
 * 网址:www.guanghangong.xyz
 */
package org.moon.framework.autoconfigure.oss.impl;

import com.aliyun.oss.ClientConfiguration;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.auth.CredentialsProvider;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.aliyun.oss.model.PutObjectResult;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.moon.framework.autoconfigure.oss.OssService;
import org.moon.framework.autoconfigure.oss.domain.MoonFile;
import org.moon.framework.autoconfigure.oss.props.OssProperties;
import org.moon.framework.autoconfigure.oss.utils.OssUtils;
import org.moon.framework.autoconfigure.utils.Func;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;

/**
 * 阿里云oss
 * @author moon
 */
@Slf4j
public class AliOssProviderImpl implements OssService,OssProvider {

    private OssProperties ossProperties;
    private OSSClient ossClient;

    @Override
    @SneakyThrows
    public OssService builder(OssProperties ossProperties) {
        // 创建ClientConfiguration。ClientConfiguration是OSSClient的配置类，可配置代理、连接超时、最大连接数等参数。
        ClientConfiguration conf = new ClientConfiguration();
        // 设置OSSClient允许打开的最大HTTP连接数，默认为1024个。
        conf.setMaxConnections(1024);
        // 设置Socket层传输数据的超时时间，默认为50000毫秒。
        conf.setSocketTimeout(50000);
        // 设置建立连接的超时时间，默认为50000毫秒。
        conf.setConnectionTimeout(50000);
        // 设置从连接池中获取连接的超时时间（单位：毫秒），默认不超时。
        conf.setConnectionRequestTimeout(1000);
        // 设置连接空闲超时时间。超时则关闭连接，默认为60000毫秒。
        conf.setIdleConnectionTime(60000);
        // 设置失败请求重试次数，默认为3次。
        conf.setMaxErrorRetry(5);
        CredentialsProvider credentialsProvider = new DefaultCredentialProvider(ossProperties.getAccessKey(), ossProperties.getSecretKey());
        this.ossClient = new OSSClient(ossProperties.getEndpoint(), credentialsProvider, conf);
        this.ossProperties = ossProperties;
        return this;
    }

    @Override
    public MoonFile putFile(MultipartFile file) {
        return putFile(file.getOriginalFilename(),file);
    }

    @Override
    public MoonFile putFile(String fileName, MultipartFile file) {
        String bucketName = OssUtils.getBucketName(ossProperties.getBucketName());
        try {
            if (!ossClient.doesBucketExist(bucketName)) {
                ossClient.createBucket(bucketName);
            }
            String originalName = fileName;
            fileName = OssUtils.getFileName(fileName);
            PutObjectResult response = ossClient.putObject(bucketName, fileName, file.getInputStream());
            int retry = 0;
            int retryCount = 5;
            while (Func.isEmpty(response.getETag()) && retry < retryCount) {
                response = ossClient.putObject(bucketName, fileName, file.getInputStream());
                retry++;
            }
            MoonFile moonFile = MoonFile.builder().originalName(fileName).name(fileName).domain(this.ossProperties.getEndpoint()).link(bucketName.concat("/").concat(fileName)).build();
            return moonFile;
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return null;
        }
    }

    @Override
    public void removeFiles(List<String> fileNames) {
        fileNames.forEach(this::removeFile);
    }

    @Override
    public void removeFile(String fileName) {
        ossClient.deleteObject(OssUtils.getBucketName(ossProperties.getBucketName()), fileName);
    }
}
